#include "my_hrtime.h"
#include "my_atomic.h"
#include "my_rwlock.h"

static char  *week[]    = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
static char  *months[]  = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
                            "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };


static my_atomic_int64_t    g_cache_time = -1;

// format: "Mon, 28 Sep 1970 06:00:00 GMT"
int64_t
my_http_time(char *buf, int64_t buf_size)
{
    if ((size_t)buf_size < MY_HRTIME_HTTP_TIME_SIZE) {
        return 0;
    }

    time_t time = my_usec_2_sec(get_cache_time());

    struct tm gmt;
    gmtime_r(&time, &gmt);
    int n  = snprintf(buf, (size_t)buf_size, "%s, %02d %s %4d %02d:%02d:%02d GMT",
        week[gmt.tm_wday], gmt.tm_mday, months[gmt.tm_mon],
        gmt.tm_year + 1900, gmt.tm_hour, gmt.tm_min, gmt.tm_sec);
    buf[n] = '\0';
    
    return n;
}

// format "2021/10/10 10:10:10"
int64_t
my_log_file_time(char *buf, int64_t buf_size)
{
    if ((size_t)buf_size < MY_LOG_FILE_TIME_SIZE) {
        return 0;
    }

    time_t time = my_usec_2_sec(get_cache_time());

    struct tm ltm;
    localtime_r(&time, &ltm);
    int n  = snprintf(buf, (size_t)buf_size, "%04d/%02d/%02d %02d:%02d:%02d",
        ltm.tm_year + 1900, ltm.tm_mon + 1, ltm.tm_mday, ltm.tm_hour, ltm.tm_min, ltm.tm_sec);
    buf[n] = '\0';    

    return n;
}

int64_t
get_cache_time()
{
    int64_t cache_time = my_atomic_int64_load(&g_cache_time);
    if (cache_time != -1) {
        return cache_time;
    }

    return get_latest_time();
}

int64_t
get_latest_time()
{
    my_timespec_t ts;
    clock_gettime(CLOCK_REALTIME, &ts);
    int64_t rs = my_ts_2_usec(&ts);

    int64_t cache_time = my_atomic_int64_load(&g_cache_time);
    if (rs > cache_time) {
        // try set, if set failed, mean cache time has been update in the current time.
        my_atomic_int64_cas(&g_cache_time, cache_time, rs);
    }

    return rs;
}